/*
* This file is a part of the open-eBackup project.
* This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
* If a copy of the MPL was not distributed with this file, You can obtain one at
* http://mozilla.org/MPL/2.0/.
*
* Copyright (c) [2024] Huawei Technologies Co.,Ltd.
*
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
*/
#ifndef NAS_SHARE_HETRO_RESTORE_H
#define NAS_SHARE_HETRO_RESTORE_H

#include <mutex>
#include "nas_share/common/HetroCommonService.h"
#include "nas_share/common/HetroBaseStruct.h"
#include "constant/PluginServiceCommon.h"
#include "define/Defines.h"
#include "define/Types.h"
#include "security/cmd/CmdParam.h"
#include "security/cmd/CmdExecutor.h"

struct TapeCopyExtendInfo {
    AggCopyExtendInfo extendInfo;
    std::string metaPath;
    std::string metaPathFSID;
    std::string multiFileSystem;
    BEGIN_SERIAL_MEMEBER
    SERIAL_MEMBER_TO_SPECIFIED_NAME(extendInfo, extendInfo)
    SERIAL_MEMBER_TO_SPECIFIED_NAME(metaPath, metaPath)
    SERIAL_MEMBER_TO_SPECIFIED_NAME(metaPathFSID, metaPathFSID)
    SERIAL_MEMBER_TO_SPECIFIED_NAME(multiFileSystem, multiFileSystem)
    END_SERIAL_MEMEBER
};
class HetroRestoreJob : public HetroBaseStruct, public HetroCommonService {
public:
    HetroRestoreJob() {}
    ~HetroRestoreJob();
    EXTER_ATTACK int PrerequisiteJob() override ;
    EXTER_ATTACK int GenerateSubJob() override ;
    EXTER_ATTACK int ExecuteSubJob() override ;
    EXTER_ATTACK int PostJob() override ;

private:
    enum class MONITOR_BACKUP_RES_TYPE {
        MONITOR_BACKUP_RES_TYPE_SUCCESS          = 0,
        MONITOR_BACKUP_RES_TYPE_FAILED           = 1,
        MONITOR_BACKUP_RES_TYPE_ABORTED          = 2,
        MONITOR_BACKUP_RES_TYPE_NEEDRETRY        = 3
    };

    int PrerequisiteJobInner();
    int GenerateSubJobInner();
    int ExecuteSubJobInner();
    int PostJobInner();
    int ExecuteRestoreSubJobInner(HetroBackupSubJob backupSubJob);
    int ExecuteCreateSubJobInner(HetroBackupSubJob backupSubJob);
    bool MountRemoteShare(std::string mountPath);
    void UnmountRemoteShare(std::string mountPath);
    int HandlePrerequisiteJobFailed(const int64_t errCode);
    int CleanAndReportDetailedStatus(const HetroBackupSubJob &backupSubJob, SubJobStatus::type jobStatus,
        std::string &jobLogLabel, std::string mountPath, BackupStats &backupStatistics);

    bool InitJobInfo();
    void GetRestoreType();
    bool InitHostInfo();
    int ExecuteCheckSubJobInner();
    bool InitFineGrainedRestoreJobInfo();
    bool InitRestoreCopyMetaInfo();
    bool PrintJobInfo();
    bool PrintJobInfoForRepoAndFilter();
    bool InitPathForRestore();
    bool UnzipDcachefiles();
    int UnzipDcachefilesInner();
    bool SetupCacheFsForRestoreJob();
    bool SetupDataFsForRestoreJob();
    bool SetupRemoteNasForRestoreJob();
    bool IsNormalRestore();
    bool IsFineGrainedHomoRestore();
    bool IsFineGrainedHetroRestore();
    bool IsHomoNewLocationRestore();
    bool IsFineGrainedHetroRestoreCifsToNative();
    bool InitRepoPaths();
    bool GetRestoreJobInfo();
    bool IsAggregate();
    std::pair<std::string, std::string> ResolveSharePathForCIFS(std::string sharePath);
    void GetJsonFilePath();

    int GenerateSubJobInnerForFileSystem();
    int StartScannerForFileSystem();
    int SpecialDealScanConfig(ScanConfig& scanConfig);
    int AddFilterRuleForFileSystem(ScanConfig& scanConfig);
    void SpecialDealScanner();
    void ClearGenerateSubJobEnv();

    int GenerateAggregateSubJobInner();
    int InitAggregateGenerateJobInfo();
    int GetRepoInfoForAggregate();
    int GetCopyExtendInfo(const int& copyOrder, AggCopyExtendInfo& aggCopyExtendInfo);
    int RecordControlFilePathForAggregate();
    int CreateSrcDirForAggregate();
    int UnzipCacheFilesForAggregate();
    void UnzipDcachefilesForAggregate(int &ret);
    int GenerateRestoreExecuteSubJobsForAggregate();
    int GenerateSubJobsForAggregateFineGrain();
    int FillScanConfigForAggregate(ScanConfig& scanConfig);
    int FillFirstScanConfigForAggregate(ScanConfig& scanConfig);
    void FillScanConfigForNative(ScanConfig &scanConfig) override;
    void FillScanConfigForAggr(ScanConfig &scanConfig) override;
    int StartToGenerateControlFileForAggregate(ScanConfig& scanConfig);
    int MoniterGenerateSubJobToCompletedForAggregate();
    int GetSpecialConfigForAggregate();
    int GetControlFileList(std::string controlFilePath, std::vector<std::string>&  contrlFileList);
    int GetExecuteSubJobType();
    int GenerateCheckSubJob();
    void HandleMonitorStuck(BackupStats &backupStatistics,
        SubJobStatus::type &jobStatus, std::string &jobLogLabel, int &jobProgress);

    template<typename... Args>
    bool ReportJobDetails(SubJobStatus::type jobStatus, int32_t jobProgress,
        std::string logLabel, const JobLogLevel::type &logLevel, Args... logArgs);

    template<typename... Args>
    bool ReportJobDetailsWithErrorCode(SubJobStatus::type jobStatus, int32_t jobProgress,
        std::string logLabel, const JobLogLevel::type &logLevel, const int64_t errCode, Args... logArgs);

    template<typename... Args>
    void ReportJobDetailsWithLabel(SubJobStatus::type jobStatus,
        const std::string& logLabel, int32_t jobProgress, std::vector<std::string> &message,
        const JobLogLevel::type &logLevel, const int64_t errCode, Args... logArgs);

    static void ScannerCtrlFileCallBack(void *usrData, const std::string &ControlFilePath);
    static void ScannerHardLinkCallBack(void *usrData, const std::string &ControlFilePath);
    static void RestoreDirMTimeCallBack(void *usrData, const std::string &ControlFilePath);
    static void RestoreDelCtrlCallBack(void *usrData, const std::string &ControlFilePath);
    bool CheckNasSharesReachable(int64_t &errCode);
    bool CheckMountVersion(std::string proto, std::string protoVersion, int64_t &errCode);
    Module::SmbVersion ConvertStringToSmbVersion(std::string versionString);
    bool CheckSmbConnectVersion(Module::SmbVersion version, int64_t &errCode);
    bool RetryUpdateBackupStartTime(HetroBackupSubJob& backupSubJob, const std::string& mountPath);

    bool StartScanner();
    bool MonitorScanner(HetroNativeScanStatistics &scanStatistics,
        SubJobStatus::type &jobStatus, std::string &jobLogStr, int &jobProgress);
    void FillMonitorScannerVarDetails(SCANNER_TASK_STATUS &scanTaskStatus,
        SubJobStatus::type &jobStatus, std::string &jobLogStr, int &jobProgress);
    bool ReportScannerRunningStatus(ScanStatistics &scanStatistics);
    bool ReportScannerCompleteStatus(ScanStatistics &scanStatistics);
    void FillScanConfigBasedOnEnviroment(ScanConfig &scanConfig);
    void FillScanConfigBasedOnProtocol(ScanConfig &scanConfig);
    void FillScanConfig(ScanConfig &scanConfig);
    void FillScanConfigForCtrlFiles(ScanConfig &scanConfig);
    void FillScanConfigForFilter(ScanConfig& scanConfig);
    bool InitSubJobInfo(SubJob &subJob, const std::string jobId, const std::string ctrlFile, uint32_t &subTaskType);
    bool HandleMonitorScannerCompletion(SubJobStatus::type &jobStatus, std::string &jobLogLabel,
        const std::string &scanCtrlFilePath, const std::string &backupCtrlFilePath);

    bool StartBackup(HetroBackupSubJob backupSubJob);
    void FillBackupNFSConfig(BackupParams &backupParams, const HetroBackupSubJob &backupSubJob);
    void FillBackupCIFSConfig(BackupParams &backupParams, const HetroBackupSubJob& backupSubJob);
    void FillBackupCommonParams(BackupParams &backupParams);
    void FillBackupConfigPhase(BackupParams &backupParams, HetroBackupSubJob &backupSubJob);
    void FillBackupConfig(BackupParams &backupParams, HetroBackupSubJob &backupSubJob);
    void FillBackupReplacePolicy(BackupParams &backupParams);
    bool UpdateBackupStatistics(BackupStats &backupStatistics);

    bool CalculateJobStats();

    bool UpdateBackupStartTimeInSharedResource(HetroBackupSubJob& backupSubJob, std::string mountPath);
    MONITOR_BACKUP_RES_TYPE MonitorBackup(BackupStats &backupStatistics,
        SubJobStatus::type &jobStatus, std::string &jobLogStr, int &jobProgress);
    bool ReportBackupRunningStatus(uint64_t currSubJobDataSize);
    bool ReportBackupCompletionStatus(HetroNativeBackupStats &backupStatistics);
    void RecordTimestamp();
    void RemoveCacheDirectories();
    void PrintBackupCopyInfo(HetroNativeBackupStats &backupStatistics);
    void ReportJobProgress(SubJobStatus::type &jobStatus, std::string &jobLogLabel);
    void ReportJobCompleteStatus(HetroNativeScanStatistics &scanStatistics, SubJobStatus::type &jobStatus,
        std::string &jobLogLabel, int &jobProgress);
    bool UpdateCopyPhaseStartTimeInGenRsc();
    bool GenerateSubJobList(std::vector<SubJob> &subJobList, std::vector<std::string> &ctrlFileList,
        const std::string &dstCtrlFileRelPath, const std::string &ctrlFileFullPath);
    bool CreateSubTasksFromCtrlFile(std::string srcDir, std::string dstDir, uint32_t subTaskType, bool isFinal = false);
    bool UpdateGeneralInfoForCopyPhase(HetroBackupSubJob& backupSubJob, std::string mountPath,
        HetroNativeGeneral& generalInfo);
    bool UpdateGeneralInfoForDeletePhase(HetroBackupSubJob& backupSubJob, std::string mountPath,
        HetroNativeGeneral& generalInfo);
    std::vector<Module::CmdParam> PrepareUnZipCommand(const std::string &mountPath, const std::string &dcache,
        const std::string &fcache, const std::string &meta, const std::string &xmeta);
    void HandleExecuteInnerError();
    void HandleMonitorComplete(SubJobStatus::type &jobStatus, std::string &jobLogLabel, int &jobProgress);
    void HandleMonitorFailed(SubJobStatus::type &jobStatus, std::string &jobLogLabel);
    void DestroyBackup();
    void HandleMonitorAbort();
    void InitServiceIp();

    /* flr method */
    bool IdentifyParamsForFLR();

    int callCheckCertThumbPrint(const AppProtect::ApplicationEnvironment& targetEnv);
    bool KinitTGT();
    void FillInfoForNasShareRestoreToNasFileSystem();
    bool PreInitJobInfo();
    void KeepPluginAlive();
    void FilterUnsupportedRemoteHost();
    /* Restore job - control phase */
    /* Restore Job */
    std::shared_ptr<AppProtect::RestoreJob> m_restoreJobPtr {};

    std::string m_dcaheAndFcachePath;
    std::string m_scanControlFilePath;
    std::string m_restoreControlFilePath;

    HetroNativeScanStatistics m_restoreScanStatistics {};
    int m_restoreJobProgress = 0;
    SubJobStatus::type m_restoreJobStatus = SubJobStatus::FAILED;
    std::string m_restoreJobLogLabel = "nas_plugin_hetro_restore_scan_fail_label";

    // 聚合格式下，用列表记录多个副本的data仓的路径
    std::vector<std::string> m_dataFsPathList;
    std::vector<std::string> m_metaFsPathList;
    std::vector<std::string> m_copyIdList;

    ScanStatistics m_scanStatistics {}; // 记录扫描总的统计信息

    std::vector<std::string> m_scanMetaPathList; // 对于聚合恢复，控制文件最终的存放路径，用于恢复的执行子任务
    std::vector<std::string> m_dcaheAndFcachePathList; // 对于聚合恢复，用于存放扫描生成的metefile文件以及解压dcache生成的文件

    std::atomic<int> m_unzipMetaFilesStatus { 0 };  // 0 = not started, -1 = failed, 1 = success

    uint32_t m_numberCopies {0};
    BackupPhase  m_backupPhase;
    HetroBackupSubJob m_subJobPathsInfo; // 记录子任务所需的信息

    AggCopyExtendInfo m_aggCopyExtendInfo;

    /* Timestamp when we last attempted to send repot to GUI */
    int64_t m_lastLogReportTime {};

    /* Data size copied to destination in MB */
    int64_t m_dataSize { 0 };
    bool m_isScannerRestarted {};

    /* Backup instance */
    std::unique_ptr<FS_Backup::Backup> m_backup {};
    BackupPhaseStatus m_backupStatus;

    /* SubTask type: CopyPhase/DelPhase/HardLinkPhase/DirMTimePhase */
    uint32_t m_subTaskType {};

    /* file level restore applicaiton resources */
    std::vector<AppProtect::ApplicationResource> m_restoreResources {};
    /* file level restore extendInfo */
    FlrRestoreExtend m_flrExtend {};
    /* file level restore type */
    FLR_RESTORE_TYPE m_flrRestoreType {};

    /* Used for reporting job progress log to agent */
    ActionResult m_logResult {};
    SubJobDetails m_logSubJobDetails {};
    LogDetail m_logDetail{};
    std::vector<LogDetail> m_logDetailList;
    std::string m_copyId;
    std::string m_tapeCopyId;
    /* Following members are used to save final information for performance analysis */
    time_t m_startTime {};
    int32_t m_totalJobDuration {};
    int32_t m_postJobDuration {};

    /* RequestId for mainJob and subJob */
    size_t m_mainJobRequestId {};
    size_t m_subJobRequestId {};
    int64_t m_lastScannerReportTime {};

    int m_maxSmbBlockSize = 0;
    std::atomic<bool> m_isUnzipInProgress { false };
    std::atomic<bool> m_generateSubjobFinish { false };
    int64_t m_lastKeepAliveReportTime { 0 };

    struct TargetEnvExtendInfo {
        std::string ip {};
        std::string kerberosId {};
        std::string shareMode {};
        BEGIN_SERIAL_MEMEBER
        SERIAL_MEMBER_TO_SPECIFIED_NAME(ip, ip)
        SERIAL_MEMBER_TO_SPECIFIED_NAME(kerberosId, kerberosId)
        SERIAL_MEMBER_TO_SPECIFIED_NAME(shareMode, shareMode)
        END_SERIAL_MEMEBER
    };
};

#endif // #define _NAS_SHARE_HETRO_RESTORE_H